from models.user_model import UserModel
from datetime import datetime
import hashlib
import os
import requests
from io import BytesIO
from PIL import Image
from utils.cache_manager import cache_manager, generate_openid_cache_key
from utils.db import execute_query, execute_update

class UserService:
    def __init__(self):
        pass  # 简化初始化，所有数据库操作都通过utils.db进行
        
    def get_user_by_openid(self, openid):
        # 首先尝试从缓存获取
        cache_key = generate_openid_cache_key(openid)
        cached_user_data = cache_manager.get(cache_key)
    
        # 如果缓存中只有session_key和unionid，需要从数据库获取完整信息
        if cached_user_data and 'user_info' in cached_user_data:
            return UserModel(**cached_user_data['user_info'])
    
        # 缓存未命中，从数据库查询
        try:
            sql = """
            SELECT * FROM users WHERE openid = %s
            """
            result = execute_query(sql, (openid,), fetch_one=True)
            
            if result:
                user = UserModel(**result)
                # 更新缓存，包含用户完整信息
                if cached_user_data:
                    # 如果已有缓存，添加用户信息
                    cached_user_data['user_info'] = result
                    cache_manager.set(cache_key, cached_user_data, 3600)  # 缓存1小时
                return user
            return None
        except Exception as e:
            print(f"查询用户失败: {str(e)}")
            return None

    def resize_avatar(self, avatar_url, size=(128, 128)):
        """调整头像图片大小"""
        if not avatar_url:
            return None
        
        try:
            # 下载图片
            response = requests.get(avatar_url, timeout=10)
            response.raise_for_status()
            
            # 打开图片并调整大小
            img = Image.open(BytesIO(response.content))
            # 保持图片比例，使用缩略图方法
            img.thumbnail(size, Image.Resampling.LANCZOS)
            
            # 如果需要保存本地，可以在这里添加保存逻辑
            # 目前只返回原图URL，因为微信头像URL本身支持参数调整大小
            # 例如：原URL + '&s=128'
            if '?' in avatar_url:
                return f"{avatar_url}&s={size[0]}"
            else:
                return f"{avatar_url}?s={size[0]}"
        except Exception as e:
            print(f"调整头像大小失败: {str(e)}")
            return avatar_url  # 如果调整失败，返回原图URL
    
    def create_user(self, user_data):
        """创建新用户"""
        try:
            # 检查用户是否已存在
            check_sql = "SELECT id FROM users WHERE openid = %s"
            if execute_query(check_sql, (user_data.get('openid'),), fetch_one=True):
                return self.update_user(user_data.get('openid'), user_data)
            
            # 处理头像缩放
            avatar_url = user_data.get('avatar_url')
            if avatar_url:
                user_data['avatar_url'] = self.resize_avatar(avatar_url)
            
            # 创建新用户
            sql = """
            INSERT INTO users (openid, session_key, unionid, nickname, avatar_url, 
                            points, last_study_time)
            VALUES (%s, %s, %s, %s, %s, %s, %s)
            """
            
            current_time = datetime.now()
            params = (
                user_data.get('openid'),
                user_data.get('session_key'),
                user_data.get('unionid'),
                user_data.get('nickname'),
                user_data.get('avatar_url'),
                user_data.get('points'),
                user_data.get('last_study_time'),
            )
            
            execute_update(sql, params)
            
            # 更新缓存信息
            openid = user_data.get('openid')
            if openid:
                cache_key = generate_openid_cache_key(openid)
                # 从数据库获取完整用户信息
                user_info = execute_query("SELECT * FROM users WHERE openid = %s", (openid,), fetch_one=True)
                
                if user_info:
                    # 获取现有的缓存数据
                    cached_data = cache_manager.get(cache_key) or {}
                    # 添加用户信息到缓存
                    cached_data['user_info'] = user_info
                    cache_manager.set(cache_key, cached_data, 3600)  # 缓存1小时
            
            # 返回创建的用户
            return self.get_user_by_openid(openid)
        except Exception as e:
            print(f"创建用户失败: {str(e)}")
            return None

    def update_user(self, openid, user_data):
        """更新用户信息，并同步更新缓存"""
        try:
            # 处理头像缩放
            if 'avatar_url' in user_data and user_data['avatar_url']:
                user_data['avatar_url'] = self.resize_avatar(user_data['avatar_url'])
            
            # 只更新提供的字段
            fields = []
            values = []
            
            for key, value in user_data.items():
                if key != 'openid' and key != 'expires_in':  # 不更新expires_in字段
                    fields.append(f"{key} = %s")
                    values.append(value)
            
            # 始终更新更新时间
            fields.append("updated_at = %s")
            values.append(datetime.now())
            
            # 添加openid到values的最后作为WHERE条件
            values.append(openid)
            
            sql = f"""
            UPDATE users SET {', '.join(fields)} WHERE openid = %s
            """
            
            execute_update(sql, values)
            
            # 更新缓存信息
            cache_key = generate_openid_cache_key(openid)
            cached_data = cache_manager.get(cache_key) or {}
            
            # 从数据库获取更新后的用户信息
            user_info = execute_query("SELECT * FROM users WHERE openid = %s", (openid,), fetch_one=True)
            
            if user_info:
                cached_data['user_info'] = user_info
                # 如果有session_key更新，也更新到缓存
                if 'session_key' in user_data:
                    cached_data['session_key'] = user_data['session_key']
                # 设置缓存过期时间（如果有提供）
                expires_in = user_data.get('expires_in')
                cache_time = 3600  # 默认缓存1小时
                if expires_in:
                    cache_time = max(0, expires_in - 60)
                cache_manager.set(cache_key, cached_data, cache_time)
            
            # 返回更新后的用户
            return self.get_user_by_openid(openid)
        except Exception as e:
            print(f"更新用户失败: {str(e)}")
            return None

    def generate_token(self, user):
        """生成用户登录token"""
        # 使用用户信息和时间戳生成token
        timestamp = datetime.now().timestamp()
        token_data = f"{user.openid}:{timestamp}:{os.urandom(8).hex()}"
        token = hashlib.sha256(token_data.encode()).hexdigest()
        
        try:
            # 检查是否已有token，有则更新
            sql = """
            SELECT id FROM user_tokens WHERE user_id = %s
            """
            result = execute_query(sql, (user.id,), fetch_one=True)
            
            current_time = datetime.now()
            expire_time = datetime.now().replace(hour=23, minute=59, second=59, microsecond=999999)  # 设置为当天23:59:59
            
            if result:
                # 更新token
                sql = """
                UPDATE user_tokens SET token = %s, expire_time = %s, updated_at = %s 
                WHERE user_id = %s
                """
                execute_update(sql, (token, expire_time, current_time, user.id))
            else:
                # 插入新token
                sql = """
                INSERT INTO user_tokens (user_id, token, expire_time, created_at, updated_at)
                VALUES (%s, %s, %s, %s, %s)
                """
                execute_update(sql, (user.id, token, expire_time, current_time, current_time))
            
            return token
        except Exception as e:
            print(f"生成token失败: {str(e)}")
            return None

    def get_user_by_token(self, token):
        """根据token查询用户"""
        try:
            sql = """
            SELECT u.* FROM users u
            JOIN user_tokens ut ON u.id = ut.user_id
            WHERE ut.token = %s AND ut.expire_time > %s
            """
            result = execute_query(sql, (token, datetime.now()), fetch_one=True)
            
            if result:
                return UserModel(**result)
            return None
        except Exception as e:
            print(f"根据token查询用户失败: {str(e)}")
            return None

# 全局用户服务实例
user_service = UserService()